package site.leiwa._01_单例模式;


import site.leiwa.common.Safe;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * 单例模式的使用场景
 * 在一个系统中，要求一个类有且仅有一个对象，如果出现多个对象就会出现“不良反应”，可以采用单例模式，具体的场景如下：
 *      ● 要求生成唯一序列号的环境；
 *      ● 在整个项目中需要一个共享访问点或共享数据，例如一个Web页面上的计数器，
 *        可以 不用把每次刷新都记录到数据库中，使用单例模式保持计数器的值，并确保是线程安全的；
 *      ● 创建一个对象需要消耗的资源过多，如要访问IO和数据库等资源；
 *      ● 需要定义大量的静态常量和静态方法（如工具类）的环境，可以采用单例模式（当 然，也可以直接声明为static的方式）
 */

// 饿汉式单例
@Safe
public class _00Singleton {

    private static final _00Singleton SINGLETON = new _00Singleton();

    // 构造方法私有化
    private _00Singleton(){}

    // 通过提供的方法获取实例对象
    public static _00Singleton getInstance(){
        return SINGLETON;
    }

    // 类中的其它方法，尽量是 static
    public static void doSomething(){

    }

    // 验证是否安全
    public static void main(String[] args) throws InterruptedException {
        ArrayList<String> list = new ArrayList<>(200);
        ArrayList<Thread> threads = new ArrayList<>(200);
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(() -> {
                try {
                    Thread.sleep(1500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                list.add(_00Singleton.getInstance().toString());
            });
            threads.add(t);
        }
        threads.forEach(Thread::start);
        Thread.sleep(2500);
        Set<String> set = new HashSet<>();
        boolean b = set.addAll(list);
        System.out.println(set.size());
    }
}